package java_thinking.unit_18_IO;

import java.io.*;

/**
 * @Desc:   java I/O输入输出
 *          1.深入理解Java中的IO :https://www.cnblogs.com/ylspace/p/8128112.html
 *
 *          1.编程语言的I/O类库中常使用 流 这个抽象概念，它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象
 *            流 屏蔽了实际I/O设备中处理数据的细节；
 *
 *          2.java I/O用到了装饰器模式，模式原理见 java_thinking/unit_15/_15_15/Decorator.java
 *
 *          3.装饰器模式也有一个缺点:在编程时，它给我们提供了相当多的灵活性，因为可以很容易的混合和匹配属性，但是它同时也增加了
 *            代码的复杂性，java I/O类库操作不便的原因在于：我们必须创建许多类如“核心”I/O类加上所有的装饰器，才能得到我们所希望
 *            的单个I/O对象;
 *
 *          4.InputStream / OutputStream 主要是面向字节形式的I/O中提供功能，
 *            而Reader / Writer则提供兼容Unicode与面向字符的I/O功能，主要是为了国际化，老的I/O流继承层次结果仅支持8位字节流，
 *            无法较好的处理16位的Unicode；Java中字符是采用Unicode标准，一个字符是16位，即一个字符使用两个字节来表示。
 *            为此，JAVA引入了处理字符的流,因为数据编码的不同，而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时，
 *            去查了指定的码表。
 *
 *          5.有时我们必须把来自于“字节”层次结构中的类和"字符"层次结构中的类结合起来使用，为了实现这个目的，要用到“适配器”类：
 *            InputStreamReader可以把InputStream转换为Reader，而OutputStreamWriter可以把OutputStream转换为Writer；
 *
 *          6.什么是缓冲、什么是缓存；区别又是什么 必看https://www.cnblogs.com/mlgjb/p/7991903.html
 *            缓冲：缓解冲击，缓存：临时存储
 *
 *          7.close()和flush()的区别与作用： 必看 https://blog.csdn.net/qq_28233015/article/details/78748628
 *            close()：关闭流，关闭流之前先要调用flush();
 *            flush():刷新缓冲区，使缓冲区数据往目标文件进行读写；
 *            原理：如果是需要频繁的对文件进行读或写,普通流的速度会比较慢,而缓冲流是在普通流的基础上多了一个缓冲区,当读或写的数
 *            据达到一定量,再自动往文件里进行读写,如果没有装满缓冲区文件就已经读(写)完毕,那么这个时候已经读写到缓冲区的数据需要
 *            手动使其朝目标文件进行读写.
 *
 *          8.若要验证第7点，可以执行 PrintWriter 尝试后不执行flush也不执行close，当两个都不执行时，输出文件会生成，但是里面没
 *            有内容，如果只执行close会发现不仅生成文件了，并且里面有内容，这说明close之前会先执行flush操作；如果单独只执行flush
 *            也会看到文件与内容，只是没关闭流而已；
 *
 *          9.流关闭顺序：先开后关(一般情况下是：先打开的后关闭，后打开的先关闭)的原则
 *            另一种情况：看依赖关系，如果流a依赖流b，应该先关闭流a，再关闭流b；
 *
 *          10. File(文件特征与管理)：用于文件或者目录的描述信息，例如生成新目录，修改文件名，删除文件，判断文件所在路径等。
 *
 *          11.字符流与字节流除了操作代码上的不同还有什么不同：
 *             1.字节流在操作时本身不会用到缓冲区(内存)，是文件本身直接操作的，案例：I_OTheory
 *             2.字符流在操作时使用了缓冲区，通过缓冲区再操作文件；案例 Character
 *             3.读写单位不同：字节流以字节(8bit)为单位，字符流以字符为单位，根据码表映射字符，一次可能读多个字节
 *             4.处理对象不同：字节流能处理所有类型的数据(如图片、avi等)，而字符流只能处理字符类型的数据
 *             5.结论：只要是处理纯文本数据，就优先考虑使用字符流。除此之外都使用字节流
 *
 *          12.开发中究竟用字节流好还是用字符流好呢：
 *             在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的，包括图片也是按字节完成，
 *             而字符是只有在内存中才会形成的，所以使用字节的操作是最多的；
 *
 *          13.java I/O库具有两个对称性，它们分别是：
 *             (1)输入-输出对称：比如InputStream和OutputStream各自占据Byte流的输入和输出的两个平行的等级结构的根部；
 *             而Reader和Writer各自占据Char流的输入和输出的两个平行的等级结构的根部。
 *             (2)byte-char对称：InputStream和Reader的子类分别负责byte和插入流的输入；OutputStream和Writer的子类分
 *             别负责byte和Char流的输出，它们分别形成平行的等级结构。
 *
 *          14.java I/O库的两个设计模式:装饰设计模式 DecoratorTheory.java 适配器设计模式Processor1.java
 *
 *
 *
 * @author: cww
 * @DateTime: 2019/5/13 19:00
 */

/**
 * 未关闭流，但是仍然在文件中生成了数据
 */
public class I_OTheory {
    static String file = "src/maindemo/java/java_thinking/unit_18_IO/I_OTheoryStream.txt";
    public static void main(String[] args) throws IOException {
        // 第1步：使用File类找到一个文件
        File f = new File(file);
        // 第2步：通过子类实例化父类对象
        OutputStream out = null;
        // 准备好一个输出的对象
        // 通过对象多态性进行实例化
        out = new FileOutputStream(f);
        // 第3步：进行写操作
        String str = "Hello World!!!";
        // 准备一个字符串
        byte b[] = str.getBytes();
        // 字符串转byte数组
        out.write(b);
        // 将内容输出
        // 第4步：关闭输出流
        // out.close();
        // 此时没有关闭
    }

}

/**
 * 不关闭流，文件中内容是空的
 * 如果想在不关闭时也可以将字符流的内容全部输出，则可以使用Writer类中的flush()方法完成
 */
class Character {
    static String file = "src/java/maindemo/java_thinking/unit_18_IO/I_OTheoryChar.txt";

    public static void main(String[] args) throws IOException {
        // 第1步：使用File类找到一个文件
        File f = new File(file);
        // 第2步：通过子类实例化父类对象
        Writer out = null;
        // 准备好一个输出的对象
        out = new FileWriter(f);
        // 通过对象多态性进行实例化
        // 第3步：进行写操作
        String str = "Hello World!!!";
        // 准备一个字符串
        out.write(str);
        // 将内容输出
        // 第4步：关闭输出流
        // out.close();
        // 此时没有关闭
        //如果想在不关闭时也可以将字符流的内容全部输出，则可以使用Writer类中的flush()方法完成
    }

}

/**
 * 输入输出时指定编码
 * InputStream中的字节编码取决文件本身的编码
 * OutputStream生成文件的编码取决于字节的编码
 * 指定java编译器编码格式：javac -encoding UTF-8 Demo.java
 */
class InOutCode {
    static String file = "src/maindemo/java/java_thinking/unit_18_IO/I_OTheoryStream.txt";
    public static void main(String[] args) throws IOException {

        InputStream in = new FileInputStream(file);
        byte[] read = new byte[]{};
        in.read(read);
        //指定读入的数组编码
        String s = new String(read,"UTF-8");
        System.out.println(s);

        OutputStream out = new FileOutputStream(file);

        out.write("我们".getBytes("UTF-8"));

//        InputStreamReader  in1 = new InputStreamReader(new FileInputStream(file),"UTF-8");
//        OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
    }
}
